﻿using FI.BatchJob.Web.Data;
using FI.BatchJob.Web.Data.Entitities;
using FI.BatchJob.Web.Services;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace FI.BatchJob.Web.Extensions
{

    /// <summary>
    /// 
    /// </summary>
    /// <seealso cref="Microsoft.Extensions.Hosting.IHostedService" />
    /// <seealso cref="System.IDisposable" />
    internal class HostSendEmailService : IHostedService, IDisposable
    {


        private readonly IServiceScopeFactory _scopeFactory;
        private Timer _timer;
        private readonly ILogger _logger;
        private readonly IEmailSender _emailSender;

        private readonly IWebHostEnvironment _hostingEnv;


        public HostSendEmailService(IServiceScopeFactory scopeFactory,
            ILogger<HostClearHistoryService> logger,
            IEmailSender emailSender,
            IWebHostEnvironment hostingEnv)
        {

            this._scopeFactory = scopeFactory;
            this._logger = logger;
            this._hostingEnv = hostingEnv;
            this._emailSender = emailSender;
        }

        public void Dispose()
        {
            _timer?.Dispose();
        }



        /// <summary>
        /// Triggered when the application host is performing a graceful shutdown.
        /// </summary>
        /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
        /// <returns></returns>
        public Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Email Sending Background Service is stopping.");

            _timer?.Change(Timeout.Infinite, 0);

            return Task.CompletedTask;
        }

        /// <summary>
        /// Triggered when the application host is ready to start the service.
        /// </summary>
        /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
        /// <returns></returns>
        public Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Email Sending Background Service is starting.");

            _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));//TimeSpan.FromSeconds(5));//

            return Task.CompletedTask;
        }

        /// <summary>
        /// Send the emails of exception.
        /// </summary>
        /// <param name="state">The state.</param>
        private void DoWork(object state)
        {
            _logger.LogInformation(string.Format("[{0:yyyy-MM-dd hh:mm:ss}]Email Sending Background Service is working.", DateTime.Now));

            var cts = new CancellationTokenSource(300000); //Cancel it if the DoWork cannot be done within 5 mins.

            ////cts.Token.Register(() => Console.WriteLine(string.Format("####[{0:yyyy-MM-dd hh:mm:ss}]Email Sending canceled.", DateTime.Now)));

            Task.Factory.StartNew(() =>
            {

                MailConfig mailConfig;

                using (var scope = _scopeFactory.CreateScope())
                {
                    var _context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                    mailConfig = _context.MailConfigs.FirstOrDefault();

                }
                if (mailConfig == null) return;


                while ((EmailQueue.Instance.EmailCount() > 0) && (!cts.Token.IsCancellationRequested))
                {

                    var workItem = EmailQueue.Instance.DequeueAsync();

                    if (workItem == null) break;

                    try
                    {
                        _emailSender.SendMail(workItem.Title, workItem.Content, mailConfig);

                        Thread.Sleep(10000);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"Error occurred executing {nameof(workItem)}.");
                    }
                }

            }, cts.Token);

        }




    }



}




